const toStringProto = Object.prototype.toString;

function is(type: string) {
  return function(obj: any): obj is any {
    return toStringProto.call(obj) === `[object ${type}]`;
  };
}

export const isDate: (obj: any) => obj is Date = is('Date');

export const isObject: (obj: any) => obj is Object = is('Object');

export function isFormData(val: any): val is FormData {
  return val !== undefined && val instanceof FormData;
}
export function isURLSearchParams(val: any): val is URLSearchParams {
  return val !== undefined && val instanceof URLSearchParams;
}

export function extend<T, U>(to: T, from: U): T & U {
  for (let key in from) {
    (<T & U>to)[key] = from[key] as any;
  }
  return to as T & U;
}

export function deepMerge(...objs: any[]) {
  const result = Object.create(null);
  objs.forEach(obj => {
    if (obj) {
      Object.keys(obj).forEach(key => {
        const val = obj[key];
        if (isObject(val)) {
          if (isObject(result[key])) {
            result[key] = deepMerge(result[key], val);
          } else {
            result[key] = deepMerge(val);
          }
        } else {
          result[key] = val;
        }
      });
    }
  });
  return result;
}
